package org.flintparticles.twoD.initializers
{
	import flash.display.Stage;
	import flash.display3D.Program3D;
	import flash.events.Event;
	
	import org.flintparticles.common.emitters.Emitter;
	import org.flintparticles.common.events.ParticleEvent;
	import org.flintparticles.common.initializers.InitializerBase;
	import org.flintparticles.common.particles.Particle;
	import org.flintparticles.common.stage3d.ShaderProgramManager;
	import org.flintparticles.common.stage3d.Stage3DManager;
	import org.flintparticles.twoD.stage3d.images.BitmapPoll;
	import org.flintparticles.twoD.stage3d.images.GeomEntity2D;
	import org.flintparticles.twoD.stage3d.images.Image2D;
	
	public class Stage3DImageBufferInitializer extends InitializerBase
	{
		private var _imageClass:Class;
		private var _parameters:Object;
		private var _buffer:Vector.<GeomEntity2D>=new Vector.<GeomEntity2D>();
		private var _stage3DManager:Stage3DManager;
		private var _bufferLength:uint=0;
		private var prog:Program3D;
		private var _bitmapPoll:BitmapPoll;
		/**
		 * imageClass -is a regular Away3D object Class 
		 * bufferLength- is the number of the image instance we want to hold in the buffer,
		 * make sure that you take into account the life length of th particle when calculating 
		 * buffer length.So that if your particles should live between 1 and 3 seconds and you spawn 
		 * steady 300 per second the buffer should be around 900 objects in total.
		 * parameters-are the rest of image Class constructor arguments
		 * */
		public function Stage3DImageBufferInitializer(stage:Stage,imageClass:Class,bufferLength:uint, parameters:Object)
		{
			_stage3DManager=Stage3DManager.getInstance(stage);
			if(_stage3DManager.context3D==null){
				_stage3DManager.addEventListener("CONTEXT3D_READY",onContextReady);
				_stage3DManager.setStage3dByIndex(0);
			}else{
				onContextReady(null);
			}
			_imageClass=imageClass;
			_parameters=parameters;
			_bufferLength=bufferLength;
		}
		private function onContextReady(e:Event):void{
			prog=_stage3DManager.shaderProgramManager.getProgramByName(ShaderProgramManager.IMAGE_PROGRAM);
			_stage3DManager.context3D.setProgram(prog);
			init();
		}
		private function init():void{
			_bitmapPoll=BitmapPoll.getInstance(_stage3DManager.context3D);
			_bitmapPoll.fromBitmapData(_parameters["bitmapdata"],false,false);
		
			var img2d:Image2D=new  _imageClass(_bitmapPoll.texture,_parameters["bitmapdata"].width,_parameters["bitmapdata"].height);
		
			img2d.context=_stage3DManager.context3D;
			initBuffer(img2d  );
			
			
		}
		private function initBuffer(img2d:Image2D):void{
			for(var i:uint=0;i<_bufferLength;++i){
				
				_buffer.push(img2d.clone());
			}
		}
		private var _firstTime:Boolean=true;
		override public function initialize( emitter:Emitter, particle:Particle):void
		{
			if(!_stage3DManager.context3D)return;
			if(_firstTime){
				emitter.addEventListener(ParticleEvent.PARTICLE_DEAD,onParticleDead,false,0,true);
				_firstTime=false;
			}
			if(_buffer.length>0){
				particle.image=_buffer.shift();
				//	trace(particle.image);
			}
			if(_buffer.length==0){
				//	do nothing
			}
		}
		override public function removedFromEmitter(emitter:Emitter) : void{
			if(emitter.hasEventListener(ParticleEvent.PARTICLE_DEAD)){
				
				emitter.removeEventListener(ParticleEvent.PARTICLE_DEAD,onParticleDead);
			}
		}
		private function onParticleDead(e:ParticleEvent):void{
			//	e.particle.isDead=false;
			//	trace(e.particle.image);
			
			_buffer.push(e.particle.image);
			trace("particle is dead!");
		}
		////////////////getters/setters//////////////////////
		/**
		 * The class to use when creating
		 * the particles' DisplayObjects.
		 */
		public function get imageClass():Class
		{
			return _imageClass;
		}
		public function set imageClass( value:Class ):void
		{
			_imageClass = value;
		}
		
		/**
		 * The parameters to pass to the constructor
		 * for the image class.
		 */
		public function get parameters():Object
		{
			return _parameters;
		}
		public function set parameters( value:Object ):void
		{
			_parameters = value;
		}
		
		
	}
}